﻿using Core.Entities;
using Core.Enums;
using Core.Reader;
using Core.ReadWriter;
using Core.Tools;
using Core.Writer;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Core.CommandProcesser
{
    /// <summary>
    /// T-SQL 命令处理器
    /// </summary>
    public class TSQLProcesser : BaseCommandProcesser
    {
        /// <summary>
        /// 储存十六进制次进阶数字。
        /// </summary>
        private static readonly int[] HexDigital;

        /// <summary>
        /// 匹配筛选参数。
        /// </summary>
        private static readonly Regex FilterParamRegex;

        /// <summary> 
        /// 匹配排序参数。
        /// </summary>
        private static readonly Regex OrderRegex;

        /// <summary>
        /// 匹配返回值参数。
        /// </summary>
        private static readonly Regex ResultRegex;

        static TSQLProcesser()
        {
            HexDigital = new int[] { 0xf, 0xf, 0xf0, 0xf00, 0xf000, 0xf0000, 0xf00000, 0xf000000 };
            
            FilterParamRegex = new Regex(@"^\[(?<Index>[0-9a-f]+)?(?<Type>OR|AND)?(?<Compare>[A-Z][A-Za-z]*)\](?<Name>([A-Za-z_]+[A-Za-z0-9_]*\.)?[A-Za-z_]+[A-Za-z0-9_]*)$");

            OrderRegex = new Regex(@"(?<Direction>[ADN])(?<Name>[A-Za-z0-9_]+)");

            ResultRegex = new Regex(@"^((?<Alias>[A-Za-z_]+[A-Za-z0-9_]*)\.)?(?<Name>[A-Za-z_]+[A-Za-z0-9_]*)$");
        }

        private readonly string FiltersCacheName = ".Filters_" + Guid.NewGuid().ToString("N");

        private readonly Dictionary<string, Action<BaseProcess, CommandInfo, DbCommand, StringBuilder>> DynamicParameters;

        /// <summary>
        /// 是否允许用户使用未定义的返回值字段进行筛选。
        /// </summary>
        public bool AllowUnknownResultFiltering { get; set; }

        /// <summary>
        /// SQL Server 连接字符串。
        /// </summary>
        private readonly string SqlConnectionString;

        /// <summary>
        /// 获得数据库连接。
        /// </summary>
        public virtual DbConnection SqlConnection
        {
            get
            {
                try
                {
                    SqlConnection Result = new SqlConnection();

                    Result.ConnectionString = SqlConnectionString;

                    if (Result.State == System.Data.ConnectionState.Closed)
                    {
                        Result.Open();
                    }

                    return Result;
                }
                catch (Exception)
                {
                    /** TODO: 异常处理 */
                    throw;
                }
            }
        }

        /// <summary>
        /// 初始化 T-SQL 命令执行器
        /// </summary>
        /// <param name="SqlConnectionString">数据库连接字符串</param>
        public TSQLProcesser(string SqlConnectionString)
        {
            this.SqlConnectionString = SqlConnectionString;

            DynamicParameters = new Dictionary<string, Action<BaseProcess, CommandInfo, DbCommand, StringBuilder>>();

            AllowUnknownResultFiltering = false;

            AddDynamicParameter("Filters", AppendFilters);
            AddDynamicParameter("Orders", AppendOrders);
        }

        /// <summary>
        /// 添加动态参数生成器。请不要在程序运行中调用此函数，因为它没有异步锁，可以在初始化程序时调用。
        /// </summary>
        /// <param name="Name">动态参数名称。</param>
        /// <param name="AppendDynamicParameter">动态参数生成委托。</param>
        public void AddDynamicParameter(string Name, Action<BaseProcess, CommandInfo, DbCommand, StringBuilder> AppendDynamicParameter)
        {
            if (Name == null)
            {
                throw new NullReferenceException("Name");
            }

            if (AppendDynamicParameter == null)
            {
                throw new NullReferenceException("AppendDynamicParameter");
            }

            if (DynamicParameters.ContainsKey(Name))
            {
                throw new ArgumentException(StringHelper.Format("Named '{0}' dynamic parameter already exists.", Name));
            }

            DynamicParameters.Add(Name, AppendDynamicParameter);
        }

        /// <summary>
        /// 获得 $Filters 参数的子项
        /// </summary>
        /// <param name="Process">处理器</param>
        /// <param name="CommandInfo">命令信息</param>
        /// <returns>返回一个筛选器集合</returns>
        private List<FilterInfo> GetFilters(BaseProcess Process, CommandInfo CommandInfo)
        {
            object TempObject;

            if (Process.Params.TryGetValue(FiltersCacheName, out TempObject))
            {
                return (List<FilterInfo>)TempObject;
            }

            List<FilterInfo> Filters = new List<FilterInfo>();

            Process.Params[FiltersCacheName] = Filters;

            TagInfo Tag = CommandInfo.InternalTag as TagInfo;

            if (Tag == null)
            {
                throw new NullReferenceException("Command not initialized.");
            }

            foreach (var Item in Process.Params)
            {
                Match Match;

                if (Item.Key.Length != 0 && Item.Key[0] == '[' && (Match = FilterParamRegex.Match(Item.Key)).Success)
                {
                    string Name = Match.Groups["Name"].Value;

                    CommandParamInfo ParamInfo;

                    if (Tag.Results.TryGetValue(Name, out ParamInfo))
                    {
                        Name = ParamInfo.Name;
                    }
                    else if(!AllowUnknownResultFiltering)
                    {
                        /* 名称不在返回值列表中，跳过此参数。 */
                        continue;
                    }

                    FilterInfo FilterInfo = new FilterInfo();

                    Group IndexGuoup = Match.Groups["Index"];
                    Group TypeGuoup = Match.Groups["Type"];

                    FilterInfo.StIndex = IndexGuoup.Success ? IndexGuoup.Value : "1";
                    FilterInfo.Index = Convert.ToInt32(FilterInfo.StIndex.Reverse(), 16);
                    FilterInfo.Type = "OR".Equals(TypeGuoup.Value, StringComparison.CurrentCultureIgnoreCase) ? OperatorTypes.Or : OperatorTypes.And;
                    FilterInfo.Compare = Match.Groups["Compare"].Value;
                    FilterInfo.Name = Name;
                    FilterInfo.Value = Item.Value;



                    Filters.Add(FilterInfo);
                }
            }

            /** 在不影响同值元素的顺序的情况下排序数组 */
            for (int i = 1, j = 0; i < Filters.Count; j = i, ++i)
            {
                FilterInfo Swap = Filters[i];
                while (Swap < Filters[j])
                {
                    Filters[j + 1] = Filters[j];
                    --j;
                    if (j == -1)
                    {
                        break;
                    }
                }
                Filters[j + 1] = Swap;
            }

            return Filters;
        }

        /// <summary>
        /// 执行读取命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="Processor">回掉函数。</param>
        /// <param name="SqlConnection">数据库连接。</param>
        public void ExecuteReader(BaseProcess Process, CommandInfo CommandInfo, Action<IDataReader> Processor, DbConnection SqlConnection)
        {
            using (DbCommand SqlCommand = SqlConnection.CreateCommand())
            {
                AppendCommand(Process, CommandInfo, SqlCommand);

                using (var DataReader = new OverrideSqlDataReader(SqlCommand.ExecuteReader(), (CommandInfo.Sign & CommandSigns.SingleObjectResult) == 0 ? RWTypes.Table : RWTypes.Object))
                {
                    Processor(DataReader);
                }
            }
        }

        /// <summary>
        /// 执行读取命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="Processor">回掉函数。</param>
        public void ExecuteReader(BaseProcess Process, CommandInfo CommandInfo, Action<IDataReader> Processor)
        {
            using (var SqlConnection = this.SqlConnection)
            {
                ExecuteReader(Process, CommandInfo, Processor, SqlConnection);
            }
        }

        /// <summary>
        /// 执行操作命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="SqlConnection">数据库连接。</param>
        /// <returns>返回受影响行数。</returns>
        public int ExecuteOperator(BaseProcess Process, CommandInfo CommandInfo, DbConnection SqlConnection)
        {
            using (DbCommand SqlCommand = SqlConnection.CreateCommand())
            {
                AppendCommand(Process, CommandInfo, SqlCommand);

                return SqlCommand.ExecuteNonQuery();
            }
        }

        /// <summary>
        /// 执行操作命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <returns>返回受影响行数。</returns>
        public int ExecuteOperator(BaseProcess Process, CommandInfo CommandInfo)
        {
            using (var SqlConnection = this.SqlConnection)
            {
                return ExecuteOperator(Process, CommandInfo, SqlConnection);
            }
        }

        /// <summary>
        /// 获得运算符的代码表现形式。
        /// </summary>
        /// <param name="OperatorType">运算符类型。</param>
        /// <returns>返回一个字符串。</returns>
        public virtual string GetOperatorString(OperatorTypes OperatorType)
        {
            switch (OperatorType)
            {
                case OperatorTypes.And:
                    return "AND";
                case OperatorTypes.Or:
                    return "OR";
                default:
                    throw new ArgumentException("OperatorType");
            }
        }

        /// <summary>
        /// 获得括号的代码表现形式。
        /// </summary>
        /// <param name="BracketType">括号类型</param>
        /// <returns>返回一个字符串。</returns>
        public virtual string GetBracketString(BracketTypes BracketType)
        {
            switch (BracketType)
            {
                case BracketTypes.Begin:
                    return "(";
                case BracketTypes.End:
                    return ")";
                default:
                    throw new ArgumentException("OperatorType");
            }
        }

        /// <summary>
        /// 获得参数值的类型。
        /// </summary>
        /// <param name="Value">参数值</param>
        /// <returns>参数类型</returns>
        public ParamTypes GetParamType(object Value)
        {
            if (Value == null)
            {
                return ParamTypes.Object;
            }

            if (Value is IConvertible)
            {
                switch (((IConvertible)Value).GetTypeCode())
                {
                    case TypeCode.Boolean:
                        return ParamTypes.Boolean;
                    case TypeCode.Char:
                    case TypeCode.String:
                        return ParamTypes.String;
                    case TypeCode.SByte:
                    case TypeCode.Byte:
                    case TypeCode.Int16:
                    case TypeCode.UInt16:
                    case TypeCode.Int32:
                        return ParamTypes.Int;
                    case TypeCode.UInt32:
                    case TypeCode.Int64:
                    case TypeCode.UInt64:
                        return ParamTypes.Long;
                    case TypeCode.Single:
                        return ParamTypes.Float;
                    case TypeCode.Double:
                    case TypeCode.Decimal:
                        return ParamTypes.Double;
                    case TypeCode.DateTime:
                        return ParamTypes.DateTime;
                }
            }

            if (Value is Guid)
            {
                return ParamTypes.Guid;
            }

            if (Value is TimeSpan)
            {
                return ParamTypes.TimeSpan;
            }

            if (Value is Array)
            {
                return ParamTypes.Ids;
            }

            return ParamTypes.Object;
        }

        /// <summary>
        /// 获得参数值的代码表现形式。
        /// </summary>
        /// <param name="ParamType">参数类型。</param>
        /// <param name="Value">参数值。</param>
        /// <returns>返回一个字符串。</returns>
        public virtual string GetParamString(ParamTypes ParamType, object Value)
        {
            if (Value == null)
            {
                return "NULL";
            }

            switch (ParamType)
            {
                case ParamTypes.Boolean:
                    return Convert.ToBoolean(Value) ? "1" : "0";
                case ParamTypes.Int:
                case ParamTypes.Long:
                case ParamTypes.Float:
                case ParamTypes.Double:
                    return Convert.ToString(Value);
                case ParamTypes.String:
                    // 将字符串中的 ' （单引号）进行转意，防止 SQL 语句被破坏（防止 SQL 注入）。
                    // 此实现只适用于 SQL Server，其他数据库请重写。
                    return "'" + Convert.ToString(Value).Replace("'", "''") + "'";
                case ParamTypes.DateTime:
                    // SQL Server 的日期格式
                    return ((DateTime)Value).ToString("yyyy/MM/dd hh:mm:ss");
                case ParamTypes.TimeSpan:
                    // TotalHours:Minutes:Seconds
                    TimeSpan TSValue = (TimeSpan)Value;
                    return (int)TSValue.TotalHours + ":" + TSValue.Minutes + ":" + TSValue.Seconds;
                case ParamTypes.Guid:
                    return ((Guid)Value).ToString("N");
                case ParamTypes.Object:
                    // Object 类型为直接写入的代码块，请慎重设置。
                    return Convert.ToString(Value);
                case ParamTypes.Ids:
                    if (Value is Array)
                    {
                        Array ArrayValue = (Array)Value;

                        if (ArrayValue.Length == 0)
                        {
                            return "";
                        }

                        if (ArrayValue.Length == 1)
                        {
                            Value = ArrayValue.GetValue(0);

                            return GetParamString(GetParamType(Value), Value);
                        }
                        else
                        {
                            // 格式 : 1,2.0,'V3',4 .....
                            StringBuilder ValueBuilder = new StringBuilder();

                            bool IsFirst = true;

                            foreach (var Item in ArrayValue)
                            {
                                if (IsFirst)
                                {
                                    IsFirst = false;
                                }
                                else
                                {
                                    ValueBuilder.Append(',');
                                }

                                ValueBuilder.Append(GetParamString(GetParamType(Item), Item));
                            }

                            return ValueBuilder.ToString();
                        }
                    }
                    else
                    {
                        return GetParamString(Value);
                    }
                default:
                    throw new ArgumentException("Unknow type not supported.");
            }
        }

        /// <summary>
        /// 获得参数值的代码表现形式。
        /// </summary>
        /// <param name="Value">参数值。</param>
        /// <returns>返回一个字符串。</returns>
        public string GetParamString(object Value)
        {
            return GetParamString(GetParamType(Value), Value);
        }

        /// <summary>
        /// 获得一个 true 表达式。
        /// </summary>
        /// <returns>返回一个字符串。</returns>
        public virtual string GetTrueString()
        {
            return "1 = 1";
        }

        /// <summary>
        /// 拼接筛选器的代码表现形式。
        /// </summary>
        /// <param name="Filter">筛选器信息。</param>
        /// <param name="SqlCommand">SQL 命令实例。</param>
        /// <param name="ParamId">参数名称的序号，如果有设置参数，请递增此值。</param>
        /// <returns>返回一个字符串。</returns>
        public virtual string GetFilterString(FilterInfo Filter, DbCommand SqlCommand, ref int ParamId)
        {
            switch (Filter.Compare)
            {
                case "E":
                    if (Filter.Value == null || Filter.Value == DBNull.Value)
                    {
                        return Filter.Name + " IS NULL";
                    }
                    else
                    {
                        return Filter.Name + " = " + GetParamString(Filter.Value);
                    }
                case "NE":
                    if (Filter.Value == null || Filter.Value == DBNull.Value)
                    {
                        return Filter.Name + " IS NOT NULL";
                    }
                    else
                    {
                        return Filter.Name + " != " + GetParamString(Filter.Value);
                    }
                case "GT":
                    return Filter.Name + " > " + GetParamString(Filter.Value);
                case "LT":
                    return Filter.Name + " < " + GetParamString(Filter.Value);
                case "GE":
                    return Filter.Name + " >= " + GetParamString(Filter.Value);
                case "LE":
                    return Filter.Name + " <= " + GetParamString(Filter.Value);
                case "Fuzzy":
                    return Filter.Name + " LIKE " + GetParamString(ParamTypes.String, "%" + Convert.ToString(Filter.Value) + "%");
                case "IN":
                    if (Filter.Value is string)
                    {
                        Filter.Value = ArrayHelper.ParseArray((string)Filter.Value);
                    }

                    if (Filter.Value is Array)
                    {
                        Array ArrayValue = (Array)Filter.Value;

                        if (ArrayValue.Length == 0)
                        {
                            throw new ArgumentException("'BW' Parameter must have 1 elements.");
                        }

                        return Filter.Name + " IN (" + GetParamString(Filter.Value) + ")";
                    }
                    else
                    {
                        throw new ArgumentException("'IN' Parameter must be 'Array' type.");
                    }
                case "BW":
                    if (Filter.Value is string)
                    {
                        Filter.Value = ArrayHelper.ParseArray((string)Filter.Value);
                    }

                    if (Filter.Value is Array)
                    {
                        Array ArrayValue = (Array)Filter.Value;

                        if (ArrayValue.Length != 2)
                        {
                            throw new ArgumentException("'BW' Parameter must have 2 elements.");
                        }

                        return Filter.Name + " BETWEEN " + GetParamString(ArrayValue.GetValue(0)) + 
                            " AND " + GetParamString(ArrayValue.GetValue(1));
                    }
                    else
                    {
                        throw new ArgumentException("'BW' Parameter must be 'Array' type.");
                    }
                case "SW":
                    return Filter.Name + " LIKE " + GetParamString(ParamTypes.String, Convert.ToString(Filter.Value) + "%");
                case "EW":
                    return Filter.Name + " LIKE " + GetParamString(ParamTypes.String, "%" + Convert.ToString(Filter.Value));
                case "NSW":
                    return Filter.Name + " NOT LIKE " + GetParamString(ParamTypes.String, Convert.ToString(Filter.Value) + "%");
                case "NEW":
                    return Filter.Name + " NOT LIKE " + GetParamString(ParamTypes.String, "%" + Convert.ToString(Filter.Value));
                case "BA":
                    return Filter.Name + " & " + GetParamString(Filter.Value) + " != 0";
                default:
                    throw new Exception("Invalid operator -- " + Filter.Compare);
            }
        }

        /// <summary>
        /// 拼接筛选器的代码表现形式。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="SqlCommand">SQL 命令实例。</param>
        /// <param name="SqlBuilder">SQL 代码字符串。</param>
        public void AppendFilters(BaseProcess Process, CommandInfo CommandInfo, DbCommand SqlCommand, StringBuilder SqlBuilder)
        {
            List<FilterInfo> Filters = GetFilters(Process, CommandInfo);

            int End = Filters.Count - 1;
            int Depth = 0;
            int ParamId = 1;

            for (int i = 0; i < Filters.Count; i++)
            {
                FilterInfo Prev = i == 0 ? FilterInfo.Empty : Filters[i - 1];
                FilterInfo Next = i == End ? FilterInfo.Empty : Filters[i + 1];
                FilterInfo Item = Filters[i];

                if (Prev != FilterInfo.Empty)
                {
                    if (Prev.Index != Item.Index)
                    {
                        while (Depth != 0 && (Prev.Index & HexDigital[Depth]) != (Item.Index & HexDigital[Depth]))
                        {
                            SqlBuilder.Append(GetBracketString(BracketTypes.End));

                            --Depth;
                        }
                    }

                    SqlBuilder.Append(" ");
                    SqlBuilder.Append(GetOperatorString(Item.Type));
                    SqlBuilder.Append(" ");
                }

                if (Prev.Index != Item.Index && (Next.Index & HexDigital[Depth]) == (Item.Index & HexDigital[Depth]))
                {
                    SqlBuilder.Append(GetBracketString(BracketTypes.Begin));

                    ++Depth;
                }

                SqlBuilder.Append(GetFilterString(Item, SqlCommand, ref ParamId));
            }

            while (Depth != 0)
            {
                SqlBuilder.Append(GetBracketString(BracketTypes.End));

                --Depth;
            }

            if (Filters.Count == 0)
            {
                SqlBuilder.Append(GetTrueString());
            }
        }

        /// <summary>
        /// 获得排序字段。
        /// </summary>
        /// <param name="Process">处理器</param>
        /// <param name="CommandInfo">命令信息</param>
        /// <returns>返回一个排序信息集合</returns>
        public List<OrderInfo> GetOrders(BaseProcess Process, CommandInfo CommandInfo)
        {
            TagInfo Tag = CommandInfo.InternalTag as TagInfo;

            if (Tag == null)
            {
                throw new NullReferenceException("Command not initialized.");
            }

            if (Tag.Results.Count == 0)
            {
                throw new ArgumentException("Results no defined.");
            }

            string Orders = Process.GetItem<string>("Orders");

            if (Orders == null)
            {
                Orders = Process.GetItem<string>("DefaultOrders");
            }

            List<OrderInfo> Result = new List<OrderInfo>();

            if (Orders == null)
            {
                goto AppendDefault;
            }

            foreach (Match MatchItem in OrderRegex.Matches(Orders))
            {
                string Direction = MatchItem.Groups["Direction"].Value;
                string Name = MatchItem.Groups["Name"].Value;

                CommandParamInfo ParamInfo;

                if (!Tag.Results.TryGetValue(Name, out ParamInfo))
                {
                    continue;
                }

                Result.Add(new OrderInfo() { Name = ParamInfo.Name, Direction = 
                    Direction == "A" ? OrderDirections.ASC : 
                    Direction == "D" ? OrderDirections.DESC : 
                    OrderDirections.None });
            }

            if (Result.Count != 0)
            {
                return Result;
            }

            AppendDefault:

            Result.Add(new OrderInfo() { Name = Tag.Results.First().Value.Name, Direction = OrderDirections.DESC });

            return Result;
        }

        /// <summary>
        /// 拼接排序字段。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="SqlCommand">SQL 命令实例。</param>
        /// <param name="SqlBuilder">SQL 代码字符串。</param>
        public virtual void AppendOrders(BaseProcess Process, CommandInfo CommandInfo, DbCommand SqlCommand, StringBuilder SqlBuilder)
        {
            var Orders = GetOrders(Process, CommandInfo);

            bool IsFirstOrder = true;

            foreach (var Item in Orders)
            {
                if (IsFirstOrder)
                {
                    IsFirstOrder = false;
                }
                else
                {
                    SqlBuilder.Append(",");
                }

                SqlBuilder.Append(Item.Name);

                switch (Item.Direction)
                {
                    case OrderDirections.ASC:
                        SqlBuilder.Append(" ASC");
                        break;
                    case OrderDirections.DESC:
                        SqlBuilder.Append(" DESC");
                        break;
                }
            }
        }

        /// <summary>
        /// 设置 SQL 代码。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="SqlCommand">SQL 命令实例。</param>
        public void AppendCommand(BaseProcess Process, CommandInfo CommandInfo, DbCommand SqlCommand)
        {
            var Tag = (TagInfo)CommandInfo.InternalTag;

            if (Tag.Codes.Length == 1 && Tag.Codes[0].Type == CodeTypes.Code)
            {
                SqlCommand.CommandText = Tag.Codes[0].Name;
            }
            else
            {
                var SqlBuilder = new StringBuilder();

                foreach (var Item in Tag.Codes)
                {
                    if (Item.Type == CodeTypes.Param)
                    {
                        Action<BaseProcess, CommandInfo, DbCommand, StringBuilder> AppendDynamicParameter;

                        if (DynamicParameters.TryGetValue(Item.Name, out AppendDynamicParameter))
                        {
                            AppendDynamicParameter(Process, CommandInfo, SqlCommand, SqlBuilder);
                        }
                        else
                        {
                            SqlBuilder.Append(GetParamString(Item.ParamType, Process[Item.Name]));
                        }
                    }
                    else if(Item.Type == CodeTypes.Code)
                    {
                        // 代码直接写入
                        SqlBuilder.Append(Item.Name);
                    }
                }

                SqlCommand.CommandText = SqlBuilder.ToString();
            }
            
            // 设置参数
            foreach (var Item in Tag.Params)
            {
                object Value = Process[Item.Name];

                DbParameter Param = SqlCommand.CreateParameter();

                Param.ParameterName = Item.Name;

                if (Value == null)
                {
                    Param.Value = DBNull.Value;
                }
                else
                {
                    Param.Value = Value;
                }

                SqlCommand.Parameters.Add(Param);
            }
        }

        /// <summary>
        /// 初始化 T-SQL 命令
        /// </summary>
        /// <param name="CommandInfo">T-SQL 命令信息</param>
        public unsafe override void Initialization(CommandInfo CommandInfo)
        {
            string TempCode = CommandInfo.Code;

            List<CommandFieldVerifier> ValidationsList = new List<CommandFieldVerifier>();

            GetValidations(ref TempCode, null, null, ValidationsList);

            CommandInfo.InternalValidations = ValidationsList.ToArray();
            
            List<CodeInfo> ConstantParams = new List<CodeInfo>();
            List<CodeInfo> VariableParams = new List<CodeInfo>();

            foreach (var Item in CommandInfo.Params)
            {
                if (Item.Name != null && Item.Name.Length >= 1)
                {
                    switch (Item.Name[0])
                    {
                        case '@':
                            Item.Name = Item.Name.Substring(1);
                            VariableParams.Add(new CodeInfo(Item.Name, Item.Type));
                            break;
                        case '$':
                            Item.Name = Item.Name.Substring(1);
                            ConstantParams.Add(new CodeInfo(Item.Name, Item.Type));
                            break;
                        default:
                            VariableParams.Add(new CodeInfo(Item.Name, Item.Type));
                            break;
                    }

                    if (Item.Name.Length >= 1)
                    {
                        continue;
                    }
                }

                throw new NullReferenceException("Parameter can not be null.");
            }


            // 名字长的排前面
            ConstantParams.Sort((Before, After) =>
            {
                return After.Name.Length - Before.Name.Length;
            });


            List<CodeInfo> Codes = new List<CodeInfo>();

            fixed (char* LpTempCode = TempCode)
            {
                int Begin = 0;
                int Index = 0;

                while ((Index = TempCode.IndexOf('$', Index)) != -1)
                {
                    ++Index;

                    foreach (var Item in ConstantParams)
                    {
                        if (StringHelper.Equals(LpTempCode, Index, TempCode.Length, Item.Name))
                        {
                            string BeforeCode = StringHelper.Substring(LpTempCode, Begin, Index - 1);

                            if (BeforeCode.Length != 0)
                            {
                                Codes.Add(new CodeInfo(BeforeCode));
                            }

                            Codes.Add(new CodeInfo(Item.Name, Item.ParamType));

                            Index += Item.Name.Length;
                            Begin = Index;
                        }
                    }
                }

                if (Begin != TempCode.Length)
                {
                    Codes.Add(new CodeInfo(StringHelper.Substring(LpTempCode, Begin, TempCode.Length)));
                }
            }

            Dictionary<string, CommandParamInfo> Results = new Dictionary<string, CommandParamInfo>();

            foreach (var Item in CommandInfo.Results)
            {
                var Match = ResultRegex.Match(Item.Name);

                if (!Match.Success)
                {
                    throw new FormatException("Result name format error! -- " + Item.Name);
                }

                Results.Add(Match.Groups["Name"].Value, Item);
            }

            CommandInfo.InternalTag = new TagInfo(Codes.ToArray(), VariableParams.ToArray(), Results);
        }

        /// <summary>
        /// 执行 T-SQL 命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="Writer">数据写入器。</param>
        public override void Process(BaseProcess Process, CommandInfo CommandInfo, IDataWriter Writer)
        {
            using (var SqlConnection = this.SqlConnection)
            {
                if ((CommandInfo.Sign & CommandSigns.Select) != 0)
                {
                    ExecuteReader(Process, CommandInfo, DataReader =>
                    {
                        Writer.ObjectType = DataReader.ObjectType;

                        var Fields = DataReader.Fields;

                        while (DataReader.Read())
                        {
                            int Index = 0;

                            Writer.Next();

                            foreach (var Item in Fields)
                            {
                                Writer.Add(Item, DataReader[Index]);

                                ++Index;
                            }
                        }

                    }, SqlConnection);

                    return;
                }

                bool NeedIdentity = (CommandInfo.Sign & CommandSigns.Insert) != 0;
                bool NeedRows = true;

                int Rows = ExecuteOperator(Process, CommandInfo, SqlConnection);

                Writer.ObjectType = RWTypes.Object;

                Writer.Next();

                if (NeedIdentity)
                {
                    int Identity = 0;

                    CommandInfo GetIdentity = Process.GetCommand("GetIdentity");

                    ExecuteReader(Process, GetIdentity, SqlDaraReader =>
                    {
                        if (SqlDaraReader.Read())
                        {
                            object ObjectIdentity = SqlDaraReader["Identity"];

                            Identity = ObjectIdentity == DBNull.Value ? 0 : Convert.ToInt32(ObjectIdentity);
                        }

                    }, SqlConnection);

                    Writer["Identity"] = Identity;
                }

                if (NeedRows)
                {
                    Writer["Rows"] = Rows;
                }

                Writer["Code"] = 0;
                Writer["Msg"] = Rows > 0 ? CommandInfo.Description + "成功" : "命令已执行，但没有数据受到影响";
            }
        }

        /// <summary>
        /// 执行 T-SQL 命令。
        /// </summary>
        /// <param name="Process">处理器。</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <param name="Callback">回掉函数。</param>
        public override void Process(BaseProcess Process, CommandInfo CommandInfo, Action<IDataReader> Callback)
        {
            using (var SqlConnection = this.SqlConnection)
            {
                if ((CommandInfo.Sign & CommandSigns.Select) != 0)
                {
                    ExecuteReader(Process, CommandInfo, Callback, SqlConnection);
                    return;
                }

                bool NeedIdentity = (CommandInfo.Sign & CommandSigns.Insert) != 0;
                bool NeedRows = true;

                int Rows = ExecuteOperator(Process, CommandInfo, SqlConnection);

                var ResultDictionary = new Dictionary<string, object>();

                if (NeedIdentity)
                {
                    int Identity = 0;

                    CommandInfo GetIdentity = Process.GetCommand("GetIdentity");

                    ExecuteReader(Process, GetIdentity, DataReader =>
                    {
                        if (DataReader.Read())
                        {
                            object ObjectIdentity = DataReader["Identity"];
                            Identity = ObjectIdentity == DBNull.Value ? 0 : Convert.ToInt32(ObjectIdentity);
                        }

                    }, SqlConnection);

                    ResultDictionary["Identity"] = Identity;
                }

                if (NeedRows)
                {
                    ResultDictionary["Rows"] = Rows;
                }

                ResultDictionary["Code"] = 0;
                ResultDictionary["Msg"] = Rows > 0 ? CommandInfo.Description + "成功" : "命令已执行，但没有数据受到影响";

                Callback(new DictionaryReadWriter(ResultDictionary));
            }
        }

        /// <summary>
        /// TSQL 命令辅助信息
        /// </summary>
        public sealed class TagInfo
        {
            /// <summary>
            /// 包含 T-SQL  代码和 $ 参数
            /// </summary>
            public readonly CodeInfo[] Codes;
            /// <summary>
            /// @ 参数
            /// </summary>
            public readonly CodeInfo[] Params;

            /// <summary>
            /// TSQL 命令返回值名称集合。
            /// </summary>
            public readonly Dictionary<string, CommandParamInfo> Results;

            /// <summary>
            /// 初始化 TSQL 命令辅助信息
            /// </summary>
            /// <param name="Codes">包含 T-SQL  代码和 $ 参数</param>
            /// <param name="Params">@ 参数</param>
            /// <param name="Results">TSQL 命令返回值名称集合。</param>
            public TagInfo(CodeInfo[] Codes, CodeInfo[] Params, Dictionary<string, CommandParamInfo> Results)
            {
                this.Codes = Codes;
                this.Params = Params;
                this.Results = Results;
            }
        }

        /// <summary>
        /// 获得用于缓存的参数值集合。
        /// </summary>
        /// <param name="Process">处理器</param>
        /// <param name="CommandInfo">命令信息。</param>
        /// <returns>返回一个值集合。</returns>
        public override object[] GetCacheParamsSign(BaseProcess Process, CommandInfo CommandInfo)
        {
            List<object> Result = new List<object>();

            var Tag = (TagInfo)CommandInfo.InternalTag;

            StringBuilder SqlBuilder = new StringBuilder();
            SqlCommand SqlCommand = new SqlCommand();

            foreach (var Item in Tag.Codes)
            {
                if (Item.Type == CodeTypes.Param)
                {
                    Action<BaseProcess, CommandInfo, DbCommand, StringBuilder> AppendDynamicParameter;

                    if (DynamicParameters.TryGetValue(Item.Name, out AppendDynamicParameter))
                    {
                        AppendDynamicParameter(Process, CommandInfo, SqlCommand, SqlBuilder);

                        Result.Add(SqlBuilder.ToString());

                        SqlBuilder.Length = 0;
                    }
                    else
                    {
                        Result.Add(GetParamString(Item.ParamType, Process[Item.Name]));
                    }
                }
            }

            foreach (DbParameter Item in SqlCommand.Parameters)
            {
                Result.Add(Item.Value);
            }

            foreach (var Item in Tag.Params)
            {
                Result.Add(Process[Item.Name]);
            }

            return Result.ToArray();
        }

        /// <summary>
        /// 表示构成 T-SQL 代码的代码片段
        /// </summary>
        public sealed class CodeInfo
        {
            /// <summary>
            /// 代码片段类型
            /// </summary>
            public readonly CodeTypes Type;
            /// <summary>
            /// 参数的类型
            /// </summary>
            public readonly ParamTypes ParamType;
            /// <summary>
            /// 代码片段名称
            /// </summary>
            public readonly string Name;

            /// <summary>
            /// 初始化参数实例
            /// </summary>
            public CodeInfo(string Name, ParamTypes ParamType)
            {
                this.Name = Name;
                this.ParamType = ParamType;

                Type = CodeTypes.Param;
            }
            /// <summary>
            /// 初始化代码实例
            /// </summary>
            /// <param name="Content">代码内容</param>
            public CodeInfo(string Content)
            {
                Name = Content;

                Type = CodeTypes.Code;
            }
        }

        /// <summary>
        /// 代码段类型
        /// </summary>
        public enum CodeTypes
        {
            /// <summary>
            /// 表示硬代码
            /// </summary>
            Code = 0x1,

            /// <summary>
            /// 表示参数
            /// </summary>
            Param = 0x2
        }

        /// <summary>
        /// 筛选器信息
        /// </summary>
        public sealed class FilterInfo
        {
            /// <summary>
            /// 筛选器索引
            /// </summary>
            public int Index;

            /// <summary>
            /// 筛选器索引的字符表现形式
            /// </summary>
            public string StIndex;

            /// <summary>
            /// 筛选器类型 AND 和 OR
            /// </summary>
            public OperatorTypes Type;

            /// <summary>
            /// 筛选器比较符
            /// E|NE|GT|LT|GE|LE|Fuzzy|IN|BW|SW|EW|NSW|NEW|BA
            /// E : Equal
            /// NE : Not Equal
            /// GT : Greater Than
            /// GE : Greater Than Or Equal
            /// LT : Less Than
            /// LE : Less Than Or Equal
            /// Fuzzy : Fuzzy
            /// IN : IN
            /// BW : Between
            /// SW : Starts With
            /// EW : Ends With
            /// NSW : Not Starts With
            /// NEW: Not Ends With
            /// BA: Bit And
            /// </summary>
            public string Compare;

            /// <summary>
            /// 字段名
            /// </summary>
            public string Name;

            /// <summary>
            /// 比较值
            /// </summary>
            public object Value;

            /// <summary>
            /// 用于排序的 < 运算符
            /// </summary>
            public static bool operator <(FilterInfo x, FilterInfo y)
            {
                return x.StIndex.CompareTo(y.StIndex) < 0;
            }

            /// <summary>
            /// 用于排序的 > 运算符
            /// </summary>
            public static bool operator >(FilterInfo x, FilterInfo y)
            {
                return x.StIndex.CompareTo(y.StIndex) > 0;
            }

            /// <summary>
            /// 一个空的实例
            /// </summary>
            public static readonly FilterInfo Empty = new FilterInfo();
        }

        /// <summary>
        /// 排序字段信息
        /// </summary>
        public sealed class OrderInfo
        {
            /// <summary>
            /// 排序字段名称
            /// </summary>
            public string Name;
            /// <summary>
            /// 排序方向
            /// </summary>
            public OrderDirections Direction;
        }

        /// <summary>
        /// 数据排序方向
        /// </summary>
        public enum OrderDirections
        {
            /// <summary>
            /// 未指定排序方向，使用数据库默认排序方向
            /// </summary>
            None,
            /// <summary>
            /// 从小到大
            /// </summary>
            ASC,
            /// <summary>
            /// 从大到小
            /// </summary>
            DESC
        }

        /// <summary>
        /// 筛选器类型 AND 和 OR
        /// </summary>
        public enum OperatorTypes
        {
            /// <summary>
            /// AND
            /// </summary>
            And = 0x1,

            /// <summary>
            /// OR
            /// </summary>
            Or = 0x2
        }

        /// <summary>
        /// 括号字符类型
        /// </summary>
        public enum BracketTypes
        {
            /// <summary>
            /// 括号开始符号
            /// </summary>
            Begin = 0x1,
            /// <summary>
            /// 括号结束符号
            /// </summary>
            End = 0x2
        }
    }
}